package com.whfc.hdc.service.impl;

import com.whfc.common.exception.BizException;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.util.SignUtil;
import com.whfc.hdc.dao.AppDeviceMapper;
import com.whfc.hdc.dto.HdcAccessTokenDTO;
import com.whfc.hdc.entity.AppDevice;
import com.whfc.hdc.params.HdcOpenApiTokenParam;
import com.whfc.hdc.redis.HdcTokenRedisDao;
import com.whfc.hdc.service.HdcOpenAccessService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author qzexing
 * @version 1.0
 * @date 2021-07-20 09:11
 */
@DubboService(interfaceClass = HdcOpenAccessService.class, version = "1.0.0")
public class HdcOpenAccessServiceImpl implements HdcOpenAccessService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final long SIGN_EXPIRES_IN_MILLS = 10 * 60 * 1000;

    private static final long OPEN_API_TOKEN_EXPIRES_IN_MILLISECONDS = 24 * 60 * 60 * 1000;

    @Autowired
    private AppDeviceMapper appDeviceMapper;

    @Autowired
    private HdcTokenRedisDao hdcTokenRedisDao;

    @Override
    public HdcAccessTokenDTO getOpenApiToken(HdcOpenApiTokenParam param) throws BizException {
        logger.info("硬件中心获取token信息, param:{}", param);
        String appKey = param.getAppKey();
        Long timestamp = param.getTimestamp();
        String sign = param.getSign();
        //验证时间戳
        if (System.currentTimeMillis() - timestamp > SIGN_EXPIRES_IN_MILLS) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "签名timestamp已过期");
        }

        //验证deviceCode
        String deviceCode = param.getDeviceCode();
        AppDevice device = appDeviceMapper.selectByCode(deviceCode);
        if (device == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "设备不存在.");
        }

        Map<String, Object> map = new HashMap<>();
        if (StringUtils.isNotBlank(appKey)) {
            map.put("appKey", param.getAppKey());
        }
        map.put("timestamp", param.getTimestamp());
        map.put("randomStr", param.getRandomStr());
        map.put("deviceCode", deviceCode);

        //验证签名
        String calSign = SignUtil.sign(map);
        logger.info("sign:[{}],calSign:[{}]", sign, calSign);
        if (!sign.equalsIgnoreCase(calSign)) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "sign不正确");
        }

        //生成accessToken
        String accessToken = UUID.randomUUID().toString().replace("-", "");
        Date now = new Date();
        Date expireTime = new Date(now.getTime() + OPEN_API_TOKEN_EXPIRES_IN_MILLISECONDS);

        HdcAccessTokenDTO tokenDTO = new HdcAccessTokenDTO();
        tokenDTO.setDeviceId(device.getId());
        tokenDTO.setSn(device.getSn());
        tokenDTO.setAccessToken(accessToken);
        tokenDTO.setExpireIn(OPEN_API_TOKEN_EXPIRES_IN_MILLISECONDS / 1000);
        tokenDTO.setExpireTime(expireTime);
        //保存到缓存中
        hdcTokenRedisDao.setAccessToken(accessToken, tokenDTO, OPEN_API_TOKEN_EXPIRES_IN_MILLISECONDS);
        return tokenDTO;
    }

    @Override
    public HdcAccessTokenDTO validateFshOpenApiToken(String accessToken) throws BizException {
        logger.info("硬件中心验证token信息, accessToken:{}", accessToken);
        HdcAccessTokenDTO token = hdcTokenRedisDao.getAccessToken(accessToken);
        if (token == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "accessToken无效");
        }
        if (System.currentTimeMillis() > token.getExpireTime().getTime()) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "accessToken已过期");
        }
        return token;
    }
}
